/*
============================================================================
 Name        : StreamReader.cpp
 Author      : 
 Version     :
 Copyright   : Your copyright notice
 Description : CStreamReader implementation
============================================================================
*/

#include "StreamReader.h"
#include "StreamBuffer.h"
#include "PluginUtility.h"

_LIT8(KStreamReaderDefaultHeaders, "User-Agent:VersificatorEngine/1.0\r\nAccept: audio/mpeg\r\n");

EXPORT_C CStreamReader::CStreamReader()
: 	iStreamBuffer(NULL), iUrlRequest(NULL), iLastChunk(NULL), iIsPendingToRead(EFalse)
{
}

EXPORT_C CStreamReader* CStreamReader::NewLC()
{
	CStreamReader* self = new (ELeave)CStreamReader();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
}

EXPORT_C CStreamReader* CStreamReader::NewL()
{
	CStreamReader* self = CStreamReader::NewLC();
	CleanupStack::Pop(); // self;
	return self;
}

EXPORT_C CStreamReader::~CStreamReader()
{
	DELETE(iUrlRequest);
	DELETE(iLastChunk);
}

EXPORT_C void CStreamReader::ConstructL()
{
	//Create a reference to connection
	iConnection = CConnection::Static();
}

EXPORT_C void CStreamReader::SetUrl(const TDesC& aUrl)
{
	DELETE(iUrlRequest)
	iUrlRequest = aUrl.Alloc();
}

EXPORT_C void CStreamReader::StartL()
{
	//Make request
	iConnection->SetObserver(this);
	iConnection->StreamingRequestL(iUrlRequest->Des(), GetAdditionalHeadersL());
}

EXPORT_C const TDesC8& CStreamReader::GetAdditionalHeadersL()
{
	return KStreamReaderDefaultHeaders;
}

EXPORT_C TDesC8& CStreamReader::ParseResponseL(TDesC8& aResponse)
{
	return aResponse;
}

void CStreamReader::SetStreamBuffer(CStreamBuffer* aStreamBuffer)
{
	iStreamBuffer = aStreamBuffer;
	iStreamBuffer->SetReader(this);
}

EXPORT_C void CStreamReader::StreamingRequestedL(TDesC8& aChunk)
{
	//Pause connection
	iConnection->Pause();

	//Write to buffer parsed response
	WriteToBuffer(ParseResponseL(aChunk));
}

void CStreamReader::WriteToBuffer(TDesC8& aChunk)
{
	if (!iStreamBuffer->IsReadyToWrite(aChunk.Length()))
	{
		//Buffer is full. We have to wait until buffer notify us throuhgt WriteToBuffer method
		iIsPendingToRead = ETrue;

		//Save last chunk
		iLastChunk = &aChunk;
		
		return;
	}

	//Write to buffer
    iStreamBuffer->Write(aChunk);
	iConnection->Resume();

	//Reset check
	iIsPendingToRead = EFalse;
}

void CStreamReader::WriteToBuffer()
{
	if (!iIsPendingToRead) return;

	if (!iStreamBuffer->IsReadyToWrite(iLastChunk->Length()))
	{
		//Buffer is not ready. We have to wait until buffer notify us throuhgt WriteToBuffer method
		return;
	}

	//Write to buffer
	WriteToBuffer(*iLastChunk);
}

EXPORT_C void CStreamReader::StreamingEndedL()
{
	iStreamBuffer->Finished();
}

EXPORT_C void CStreamReader::ResponseErrorL(TInt aError)
{
}